﻿namespace WGController32_CSharp
{
    using System;
    using System.Runtime.InteropServices;
    using WG3000_COMM.Core;

    public class WGPacketShort : IDisposable
    {
        private wgMjController controller = new wgMjController();
        public const int ControllerPort = 0xea60;
        public byte[] data = new byte[0x38];
        public int functionID;
        public long iDevSn;
        public string IP;
        public byte[] recv = new byte[0x40];
        private static long sequenceId;
        public const long SpecialFlag = 0x55aaaa55L;
        public const int Type = 0x17;
        public const int WGPacketSize = 0x40;

        public WGPacketShort()
        {
            this.Reset();
        }

        public void close()
        {
            this.controller.Dispose();
        }

        public static int Decrypt(ref byte[] command, byte[] password)
        {
            IntPtr destination = Marshal.AllocHGlobal(0x40);
            Marshal.Copy(command, 0, destination, 0x40);
            IntPtr ptr2 = Marshal.AllocHGlobal(0x10);
            Marshal.Copy(password, 0, ptr2, 0x10);
            int num = ShortDecrypt(destination, ptr2);
            if (num > 0)
            {
                Marshal.Copy(destination, command, 0, 0x40);
            }
            Marshal.FreeHGlobal(destination);
            Marshal.FreeHGlobal(ptr2);
            return num;
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing && (this.controller != null))
            {
                this.controller.Dispose();
            }
        }

        public static int Encrypt(ref byte[] command, byte[] password)
        {
            IntPtr destination = Marshal.AllocHGlobal(0x40);
            Marshal.Copy(command, 0, destination, 0x40);
            IntPtr ptr2 = Marshal.AllocHGlobal(0x10);
            Marshal.Copy(password, 0, ptr2, 0x10);
            int num = ShortEncrypt(destination, ptr2);
            if (num > 0)
            {
                Marshal.Copy(destination, command, 0, 0x40);
            }
            Marshal.FreeHGlobal(destination);
            Marshal.FreeHGlobal(ptr2);
            return num;
        }

        public void Reset()
        {
            for (int i = 0; i < 0x38; i++)
            {
                this.data[i] = 0;
            }
        }

        public int run()
        {
            byte[] cmd = this.toByte();
            int num = 3;
            int num2 = 0;
            this.controller.IP = this.IP;
            this.controller.PORT = 0xea60;
            do
            {
                if (this.controller.ShortPacketSend(cmd, ref this.recv) >= 0)
                {
                    long num3 = 0L;
                    for (int i = 0; i < 4; i++)
                    {
                        long num5 = this.recv[40 + i];
                        num3 += num5 << (8 * i);
                    }
                    if (((this.recv[0] == 0x17) && (this.recv[1] == this.functionID)) && (num3 == sequenceId))
                    {
                        return 1;
                    }
                    num2++;
                }
            }
            while (num-- > 0);
            return -1;
        }

        public int run(string pcIPAddress)
        {
            byte[] cmd = this.toByte();
            int num = 3;
            int num2 = 0;
            this.controller.IP = this.IP;
            this.controller.PORT = 0xea60;
            do
            {
                if (this.controller.ShortPacketSend(cmd, ref this.recv, pcIPAddress) >= 0)
                {
                    long num3 = 0L;
                    for (int i = 0; i < 4; i++)
                    {
                        long num5 = this.recv[40 + i];
                        num3 += num5 << (8 * i);
                    }
                    if (((this.recv[0] == 0x17) && (this.recv[1] == this.functionID)) && (num3 == sequenceId))
                    {
                        return 1;
                    }
                    num2++;
                }
            }
            while (num-- > 0);
            return -1;
        }

        public int run(byte[] commPassword)
        {
            byte[] command = this.toByte();
            Encrypt(ref command, commPassword);
            int num = 3;
            int num2 = 0;
            this.controller.IP = this.IP;
            this.controller.PORT = 0xea60;
            do
            {
                if (this.controller.ShortPacketSend(command, ref this.recv) >= 0)
                {
                    if ((this.recv[0] & 0x7f) == 0x17)
                    {
                        Decrypt(ref this.recv, commPassword);
                        long num3 = 0L;
                        for (int i = 0; i < 4; i++)
                        {
                            long num5 = this.recv[40 + i];
                            num3 += num5 << (8 * i);
                        }
                        if (((this.recv[0] == 0x17) && (this.recv[1] == this.functionID)) && (num3 == sequenceId))
                        {
                            return 1;
                        }
                        num2++;
                    }
                    else
                    {
                        num2++;
                    }
                }
            }
            while (num-- > 0);
            return -1;
        }

        public int run1024(byte[] buff) => 
            this.run1024(buff, null);

        public int run1024(byte[] buff, byte[] commPassword)
        {
            long num = 0L;
            for (int i = 0; i < 4; i++)
            {
                long num3 = buff[40 + i];
                num += num3 << (8 * i);
            }
            if (commPassword != null)
            {
                byte[] destinationArray = new byte[0x40];
                for (int j = 0; j < 0x400; j += 0x40)
                {
                    Array.Copy(buff, j, destinationArray, 0, 0x40);
                    Encrypt(ref destinationArray, commPassword);
                    Array.Copy(destinationArray, 0, buff, j, 0x40);
                }
            }
            int num5 = 3;
            int num6 = 0;
            this.controller.IP = this.IP;
            this.controller.PORT = 0xea60;
            do
            {
                if (this.controller.ShortPacketSend(buff, ref this.recv) >= 0)
                {
                    if ((((this.recv[0] & 0x7f) == 0x17) && (commPassword != null)) && (this.recv.Length == 0x400))
                    {
                        byte[] buffer2 = new byte[0x40];
                        for (int m = 0; m < 0x400; m += 0x40)
                        {
                            Array.Copy(this.recv, m, buffer2, 0, 0x40);
                            Decrypt(ref buffer2, commPassword);
                            Array.Copy(buffer2, 0, this.recv, m, 0x40);
                        }
                    }
                    long num8 = 0L;
                    for (int k = 0; k < 4; k++)
                    {
                        long num10 = this.recv[40 + k];
                        num8 += num10 << (8 * k);
                    }
                    if (((this.recv[0] == 0x17) && (this.recv[1] == this.functionID)) && (num8 == num))
                    {
                        return 1;
                    }
                    num6++;
                }
            }
            while (num5-- > 0);
            return -1;
        }

        public static long sequenceIdSent() => 
            sequenceId;

        [DllImport("n3kWGCom.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Auto)]
        private static extern int ShortDecrypt(IntPtr command, IntPtr password);
        [DllImport("n3kWGCom.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Auto)]
        public static extern int ShortEncrypt(IntPtr command, IntPtr password);
        public byte[] toByte()
        {
            byte[] destinationArray = new byte[0x40];
            sequenceId += 1L;
            destinationArray[0] = 0x17;
            destinationArray[1] = (byte) this.functionID;
            Array.Copy(BitConverter.GetBytes(this.iDevSn), 0, destinationArray, 4, 4);
            Array.Copy(this.data, 0, destinationArray, 8, this.data.Length);
            Array.Copy(BitConverter.GetBytes(sequenceId), 0, destinationArray, 40, 4);
            return destinationArray;
        }
    }
}

